﻿namespace VIT.BusinessLogicLayer.CRM
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Mail;

    using VIT.BusinessLogicLayer;
    using VIT.DataAccessLayer.CRM;
    using VIT.DataSource;
    using VIT.DataTransferObjects;
    using VIT.DataTransferObjects.Admin.Config;
    using VIT.Entity.CRM;
    using VIT.Library;
    using VIT.Provider;

    public class CustomerBLL : BLLBase
    {
        private readonly IAgentDAL _agentDAL;
        private readonly IContactDAL _contactDAL;
        private readonly IHistoryDAL _historyDAL;
        private readonly IContractDAL _contractDAL;
        private readonly ITransactionDAL _transactionDAL;

        public CustomerBLL(string connectionString = "")
            : base(connectionString)
        {
            this._agentDAL = new AgentDAL(this.DatabaseFactory);
            this._contactDAL = new ContactDAL(this.DatabaseFactory);
            this._historyDAL = new HistoryDAL(this.DatabaseFactory);
            this._contractDAL = new ContractDAL(this.DatabaseFactory);
            this._transactionDAL = new TransactionDAL(this.DatabaseFactory);
        }

        public IList<CustomerStatusDto> GetAllCustomerByAgent(string agent, IList<int> status)
        {
            var config = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => new { e.FreeDay, e.ConnectionString })
                .FirstOrDefault();

            if (config != null)
            {
                var companyBLL = new CompanyBLL(config.ConnectionString);
                var webs = companyBLL.GetAllWebsite(config.FreeDay);
                webs = webs.Where(e => status.Contains(e.StatusId)).ToList();
                return webs;
            }

            return new List<CustomerStatusDto>();
        }

        public IList<string> GetDomainsByCustomer(string agent, string customer)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
                var companyBLL = new CompanyBLL(connection);
                return companyBLL.GetDomainsByDomain(customer);
            }

            return new List<string>();
        }

        public IList<string> GetTemplatesByCustomer(string agent, string customer)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
                var companyBLL = new CompanyBLL(connection);
                return companyBLL.GetTemplatesByDomain(customer);
            }

            return new List<string>();
        }

        public PriceDto Thunhap()
        {
            var dto = new PriceDto();
            dto.TongThu = this._contractDAL.GetAll().Sum(e => e.Price);
            dto.TongChi = this._contractDAL.GetAll().Where(e => e.ServiceId == 6 || e.ServiceId == 7).Sum(e => e.Price);
            dto.ThuMoiNam = this._contractDAL.GetAll().Where(e => e.Repeat == true).Sum(e => e.Price);
            dto.ChiMoiNam = this._contractDAL.GetAll().Where(e => e.ServiceId == 7).Sum(e => e.Price);

            return dto;
        }

        public string CreateKey(string agent, string customer, int years, IList<string> domains, string user)
        {
            var agentConfig = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => new { e.ConnectionString, e.FreeDay })
                .FirstOrDefault();

            if (agentConfig != null)
            {
                typeof(AppSettings).GetProperty("FreeDay").SetValue(SettingsManager.AppSettings, agentConfig.FreeDay, null);

                var companyBLL = new CompanyBLL(agentConfig.ConnectionString);
                var webconfigBLL = new WebConfigProvider(agentConfig.ConnectionString);
                
                var companyId = companyBLL.GetCompanyIdByDomain(customer);
                var webconfig = webconfigBLL.GetByCompany(companyId);

                var license = this.CreateLicense(years, webconfig.ExperDate, domains);

                // luu history
                var history = new History();
                history.Date = DateTime.Now;
                history.Domain = customer;
                history.Action = string.Format("CreateKey:Y[{0}]K[{1}]", years, license);
                history.UserName = user;
                this._historyDAL.Add(history);
                this.SaveChanges();

                return license;
            }

            return customer;
        }
        
        public void UpdateKey(string agent, string customer, int years, string keys, string user)
        {
            var agentConfig = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => new { e.ConnectionString, e.FreeDay })
                .FirstOrDefault();

            if (agentConfig != null)
            {
                typeof(AppSettings).GetProperty("FreeDay").SetValue(SettingsManager.AppSettings, agentConfig.FreeDay, null);

                var companyBLL = new CompanyBLL(agentConfig.ConnectionString);
                var webconfigBLL = new WebConfigProvider(agentConfig.ConnectionString);

                var companyId = companyBLL.GetCompanyIdByDomain(customer);
                var webconfig = webconfigBLL.GetByCompany(companyId);
                webconfig.Keys = keys;
                webconfig.Years = years;
                webconfigBLL.Update(webconfig, user, companyId);

                // luu history
                var history = new History();
                history.Date = DateTime.Now;
                history.Domain = customer;
                history.Action = string.Format("UpdateKey:Y[{0}]K[{1}]", webconfig.Years, webconfig.Keys);
                history.UserName = user;
                this._historyDAL.Add(history);
                this.SaveChanges();
            }
        }

        public void SendKey(string email, string keys, int year, string customer, string user)
        {
            // send email
            const string Email_ = "zicki.vn@gmail.com";
            const string PassWord = "123qwwe!@#";
            const int Port = 587;
            const string Host = "smtp.gmail.com";
            const bool EnableSsl = true;

            var title = "License zicki.vn";
            var body = "Xin chao!<br />";
            body += "Xin chuc mung Quy khach da tro thanh khach hang cua Zicki.vn<br /><br />";
            body += "Domain cua Quy khach da duoc dang ky !";
            body += "<table style='BORDER-COLLAPSE:collapse;FONT-FAMILY:Arial;FONT-SIZE:10pt' border='1' cellpadding='3' cellspacing='0' width='100%'>";
            body += "<tbody><tr><td bgcolor='#eeeeee' width='100%'><font color='#000080'><b>Thong Tin License</b></font></td></tr>";
            body += "<tr><td width='100%'><p><font face='Arial' size='2'><br>";
            body += "- Key: " + keys + "<br />";
            body += "- So nam dang ky: " + year + " (ke tu ngay dang ky)<br />";
            body += "- Quy khach co the vao day hoan tat dang ky: <a href='http://admin.zicki.vn/vit-config-webconfig' target='_blank'>http://admin.zicki.vn/vit-config-webconfig</a>";
            body += "</font></p></td></tr></tbody></table>";

            var smtp = new SmtpClient();
            var msg = new MailMessage(Email_, email, title, body);
            msg.IsBodyHtml = true;
            smtp.Host = Host; //Sử dụng SMTP của gmail
            smtp.Port = Port;
            smtp.EnableSsl = EnableSsl;
            smtp.UseDefaultCredentials = true;
            smtp.Credentials = new System.Net.NetworkCredential(Email_, PassWord);
            smtp.Send(msg);

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = customer;
            history.Action = string.Format("SendKey:E[{0}]K[{1}]", email, keys);
            history.UserName = user;
            this._historyDAL.Add(history);
            this.SaveChanges();
        }

        public CustomerDetailDto GetCustomerByDomain(string agent, string domain)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
                var companyBLL = new CompanyBLL(connection);
                return companyBLL.GetCompanyDetailByDomain(domain);
            }

            return new CustomerDetailDto();
        }

        public IList<CustomerContactDto> GetContactByDomain(string domain)
        {
            var data = this._contactDAL.GetAll()
                .Where(e => e.Domain.ToLower() == domain.ToLower())
                .Select(e => new CustomerContactDto
                    {
                        ContactFrom = e.ContactFrom,
                        Id = e.Id,
                        Date = e.Date,
                        Note = e.Note,
                        Reason = e.Reason,
                        UserName = e.UserName
                    })
                .ToList();

            return data;
        }

        public IList<CustomerContractDto> GetContractByDomain(string domain)
        {
            var data = this._contractDAL.GetAll()
                .Where(e => e.Domain.ToLower() == domain.ToLower())
                .Select(e => new CustomerContractDto
                {
                    Id = e.Id,
                    Price = e.Price,
                    Repeat = e.Repeat,
                    ServiceId = e.ServiceId
                })
                .ToList();

            if (data.Count > 0)
                data.ForEach(e => e.ServiceName = DataSource.CRMServiceCollection
                    .Where(o => o.Id == e.ServiceId)
                    .Select(o => o.Name)
                    .FirstOrDefault());

            return data;
        }

        public void InsertContactIntoCustomer(string domain, string method, int reasonId, string note, string user)
        {
            var contact = new Contact();
            contact.Domain = domain;
            contact.ContactFrom = method;
            contact.Reason = DataSource.CRMContactReasonCollection.FirstOrDefault(e => e.Id == reasonId).Name;
            contact.Note = note;
            contact.Date = DateTime.Now;
            contact.UserName = user;
            this._contactDAL.Add(contact);

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = domain;
            history.Action = string.Format("Contact:M[{0}]R[{1}]N[{2}]", contact.ContactFrom, contact.Reason, contact.Note);
            history.UserName = user;
            this._historyDAL.Add(history);

            this.SaveChanges();
        }

        public void DeleteDomain(string id, string agent, string customer, string domain, string user)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
                var companyBLL = new CompanyBLL(connection);

                var companyId = companyBLL.GetCompanyIdByDomain(customer);
                companyBLL.RemoveDomainCompany(companyId, domain);
            }

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = domain;
            history.Action = string.Format("DeleteDomain:W[{0}]D[{1}]A[{2}]", id, domain, agent);
            history.UserName = user;
            this._historyDAL.Add(history);

            this.SaveChanges();
        }

        public void AddDomain(string id, string agent, string customer, string domain, string user)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
                var companyBLL = new CompanyBLL(connection);

                var companyId = companyBLL.GetCompanyIdByDomain(customer);
                companyBLL.AddDomainCompany(companyId, domain);
            }

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = domain;
            history.Action = string.Format("AddDomain:W[{0}]D[{1}]A[{2}]", id, domain, agent);
            history.UserName = user;
            this._historyDAL.Add(history);

            this.SaveChanges();
        }

        public void DeleteTemplate(string domain, string agent, string template, string user)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
            }

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = domain;
            history.Action = string.Format("DeleteTemplate:W[{0}]T[{1}]A[{2}]", domain, template, agent);
            history.UserName = user;
            this._historyDAL.Add(history);

            this.SaveChanges();
        }

        public void AddTemplate(string domain, string agent, string template, string user)
        {
            var connection = this._agentDAL.GetAll()
                .Where(e => e.Domain.ToLower() == agent.ToLower())
                .Select(e => e.ConnectionString)
                .FirstOrDefault();

            if (connection != null)
            {
            }

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = domain;
            history.Action = string.Format("AddTemplate:W[{0}]T[{1}]A[{2}]", domain, template, agent);
            history.UserName = user;
            this._historyDAL.Add(history);

            this.SaveChanges();
        }

        public void DeleteService(string domain, int serviceId, string user)
        {
            var service = this._contractDAL.Get(e => e.Id == serviceId && e.Domain == domain);
            if (service != null)
            {
                var transaction = new Transaction();
                transaction.Action = false;
                transaction.DateTime = DateTime.Now;
                transaction.Domain = service.Domain;
                transaction.ServiceId = service.ServiceId;
                transaction.Price = service.Price;
                transaction.Repeat = service.Repeat;

                this._transactionDAL.Add(transaction);
                this._contractDAL.Delete(service);

                // luu history
                var history = new History();
                history.Date = DateTime.Now;
                history.Domain = domain;
                history.Action = string.Format("DeleteService:W[{0}]S[{1}]", domain, serviceId);
                history.UserName = user;
                this._historyDAL.Add(history);

                this.SaveChanges();
            }
        }

        public void AddService(string domain, int serviceId, decimal price, bool repeat, string user)
        {
            var service = new Contract();
            service.ServiceId = serviceId;
            service.Price = price;
            service.Domain = domain;
            service.Repeat = repeat;
            this._contractDAL.Add(service);

            var transaction = new Transaction();
            transaction.Action = false;
            transaction.DateTime = DateTime.Now;
            transaction.Domain = service.Domain;
            transaction.ServiceId = service.ServiceId;
            transaction.Price = service.Price;
            transaction.Repeat = service.Repeat;
            this._transactionDAL.Add(transaction);

            // luu history
            var history = new History();
            history.Date = DateTime.Now;
            history.Domain = domain;
            history.Action = string.Format("AddService:W[{0}]S[{1}]P[{2}]R[{3}]", domain, serviceId, price, repeat);
            history.UserName = user;
            this._historyDAL.Add(history);

            this.SaveChanges();
        }

        #region privete method
        private string CreateLicense(int years, DateTime? experDate, IList<string> domains)
        {
            // da dang ky
            if (experDate == null)
            {
                experDate = DateTime.Now;
            }

            experDate = experDate.Value.AddYears(years);

            var keys = new List<string>();
            foreach (var domain in domains)
            {
                var licenseToken = (domain + experDate.Value.ToString("dd/MM/yyyy")).EnCode(SettingsManager.AppSettings.FreeDay);
                var key = Encrypt.CreateLicense(domain, experDate.Value, licenseToken, SettingsManager.AppSettings.FreeDay);
                keys.Add(key);
            }

            var license = string.Join("|", keys.Distinct());
            return license;
        }
        #endregion
    }
}
